const state = {
  websocket: undefined,
  socketMsgQueue: [],
  isConnected: false, // 连接状态
  messageListeners: new Map()
}

const mutations = {
  connetSocket: (state, wxopid) => {
    console.info('连接websocket...')
    state.websocket = wx.connectSocket({
      url: process.env.SOCKET_BASE_API + '/websocket/' + wxopid
    })
  },
  sendMessage: (state, message) => {
    console.info('发送消息' + message)
    // 已连接直接发送，未连接放入消息队列
    if (state.isConnected === true) {
      state.websocket.send(message)
    } else {
      state.socketMsgQueue.push(message)
    }
  },
  addMsgListener(state, {name, listener}) {
    console.info('添加加消息监听器：' + name)
    if (listener instanceof Function) {
      state.messageListeners.set(name, listener)
    } else {
      throw new Error('参数类型错误，请传入回调函数')
    }
  },
  removeMsgListener(state, name) {
    console.info('移除消息监听器：' + name)
    state.messageListeners.delete(name)
  }
}

const actions = {
  initSocket({ commit, dispatch, state, rootState }, wxopid) {
    if (state.isConnected === true) return
    commit('connetSocket', wxopid)
    state.websocket.onOpen(res => {
      console.info('websocket连接成功')
      state.isConnected = true
      const data = { // 设置客户端信息
        data: JSON.stringify({
          type: 'data',
          data: {
            wxopid: rootState.wxopid,
            wxyhnc: rootState.wxyhnc,
            wxyhxb: rootState.wxyhxb,
            wxyhtx: rootState.wxyhtx,
            latitude: rootState.latitude,
            longitude: rootState.longitude
          }
        })
      }
      commit('sendMessage', data)
      while (state.socketMsgQueue.length > 0) {
        const msg = state.socketMsgQueue.shift()
        commit('sendMessage', msg)
      }
    })
    state.websocket.onMessage(res => {
      console.info('websocket收到消息' + res.data)
      // 分发消息
      state.messageListeners.forEach((listener, name) => {
        try {
          listener(res.data)
        } catch (e) {
          console.error(e)
        }
      })
    })
    state.websocket.onError(error => {
      state.isConnected = false
      console.info('socketet异常')
      console.info(error)
    })
    state.websocket.onClose(res => {
      console.info('连接关闭')
      state.isConnected = false
      dispatch('initSocket', wxopid) // 尝试重连
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
